/*******************************************************************************
 * Copyright (c) 2002 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 ******************************************************************************/
package net.sourceforge.perforce.ui.views;

import java.util.ArrayList;
import java.util.List;

import net.sourceforge.perforce.core.resources.IP4File;
import net.sourceforge.perforce.core.syncinfo.ResourceSyncInfo;
import net.sourceforge.perforce.ui.OverlayIcon;
import net.sourceforge.perforce.ui.OverlayIconCache;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;

/**
  * @version $Revision: 212 $
  * @author  <a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  */
public class ChangelistViewDecorator extends LabelProvider implements ILabelDecorator 
{
	// --------------------------------------------------------------------------- Private Variables
		
	/** The OverlayIconCache. */
	private OverlayIconCache iconCache = new OverlayIconCache();

	// ------------------------------------------------------------ Public Methods (ILabelDecorator)
		
	/** @see ILabelDecorator#decorateImage(Image, Object) */
	public Image decorateImage(Image image, Object element) 
	{
		if (!(element instanceof IP4File))
		{
			return image;
		}
		
		IP4File file = (IP4File) element;
		DecoratorOverlayIcon decoratedImage = decorateImage(image, file);				
		if (decoratedImage == null)
		{			
			return image;
		}
			
		return iconCache.getImageFor(decoratedImage);
	}

	/** @see ILabelDecorator#decorateText(String, Object) */
	public String decorateText(String text, Object element) 
	{
		return text;
	}

	// --------------------------------------------------------- Public Methods (IBaseLabelProvider)
	
	/** @see IBaseLabelProvider#dispose() */
	public void dispose() 
	{
		iconCache.disposeAll();
	}

	// ----------------------------------------------------------------------------- Private Methods

	/** Called to calcludate the DecoratorOverlayIcon for the given IP4File.
	  * 
	  * @param image the image to decorate.
	  * @param file the file.
	  * @return the decoration.
	  */
	private DecoratorOverlayIcon decorateImage(Image image, IP4File file) 
	{
		List overlays = new ArrayList();
		List locations = new ArrayList();
		
		boolean ourFile = file.getClientName().equals(file.getServer().getClient());
				
		if (file.getAction().equals(ResourceSyncInfo.ACTION_ADD))
		{
			if (ourFile)
			{
				overlays.add(OverlayIconCache.OPEN_FOR_ADD);
				locations.add(new Integer(OverlayIconCache.OPEN_FOR_ADD_LOCATION));
			}
			else
			{
				overlays.add(OverlayIconCache.OTHER_OPEN_FOR_ADD);
				locations.add(new Integer(OverlayIconCache.OTHER_OPEN_FOR_ADD_LOCATION));
			}
		}
		if (file.getAction().equals(ResourceSyncInfo.ACTION_BRANCH))
		{
			if (ourFile)
			{
				overlays.add(OverlayIconCache.OPEN_FOR_ADD);
				locations.add(new Integer(OverlayIconCache.OPEN_FOR_ADD_LOCATION));
			}
			else
			{
				overlays.add(OverlayIconCache.OTHER_OPEN_FOR_ADD);
				locations.add(new Integer(OverlayIconCache.OTHER_OPEN_FOR_ADD_LOCATION));
			}
		}
		else
		if (file.getAction().equals(ResourceSyncInfo.ACTION_DELETE))
		{
			if (ourFile)
			{
				overlays.add(OverlayIconCache.OPEN_FOR_DELETE);
				locations.add(new Integer(OverlayIconCache.OPEN_FOR_DELETE_LOCATION));
			}
			else
			{
				overlays.add(OverlayIconCache.OTHER_OPEN_FOR_DELETE);
				locations.add(new Integer(OverlayIconCache.OTHER_OPEN_FOR_DELETE_LOCATION));
			}
		}
		else
		if (file.getAction().equals(ResourceSyncInfo.ACTION_EDIT))
		{
			if (ourFile)
			{
				overlays.add(OverlayIconCache.OPEN_FOR_EDIT);
				locations.add(new Integer(OverlayIconCache.OPEN_FOR_EDIT_LOCATION));
			}
			else
			{
				overlays.add(OverlayIconCache.OTHER_OPEN_FOR_EDIT);
				locations.add(new Integer(OverlayIconCache.OTHER_OPEN_FOR_EDIT_LOCATION));
			}
		}
		
		if (file.needsResolve())
		{
			overlays.add(OverlayIconCache.OUT_OF_DATE);
			locations.add(new Integer(OverlayIconCache.OUT_OF_DATE_LOCATION));
		}
		
		if (file.hasOurLock())
		{
			overlays.add(OverlayIconCache.OUR_LOCK);
			locations.add(new Integer(OverlayIconCache.OUR_LOCK_LOCATION));
		}
				
		if (overlays.isEmpty())
		{
			return null;
		}
		else
		{
			Integer[] integers = (Integer[]) locations.toArray(new Integer[locations.size()]);
			int[] ints = new int[integers.length];
			for (int i = 0; i < integers.length; i++) 
			{
				ints[i] = integers[i].intValue();
			}
			
			ImageDescriptor[] imageDescriptors =
				(ImageDescriptor[]) overlays.toArray(new ImageDescriptor[overlays.size()]);			
			return new DecoratorOverlayIcon(image, imageDescriptors, ints);
		}
	}
	
	// ---------------------------------------------------------------------- Private Nested Classes
		
	/** The decorator's OverlayIcon. */
	private static class DecoratorOverlayIcon extends OverlayIcon 
	{
		// --------------------------------------------------------------------- Public Constructors
		
		/** Constructor for DecoratorOverlayIcon.
		  *
		  * @param base the base iamge.
		  * @param overlays the overlay to apply.
		  * @param locations the locations of the overlays. 
		  */
		public DecoratorOverlayIcon(Image base, ImageDescriptor[] overlays, int[] locations) 
		{
			super(
				base, 
				overlays, 
				locations, 
				new Point(base.getBounds().width, base.getBounds().height));
		}
		
		// ----------------------------------------------------------------------- Protected Methods
		
		/** @see OverlayIcon#drawOverlays(ImageDescriptor[]) */
		protected void drawOverlays(ImageDescriptor[] overlays, int[] locations) 
		{
			Point size = getSize();
			for (int i = overlays.length - 1; i >= 0; --i) 
			{
				ImageData imageData = overlays[i].getImageData();
				
				switch (locations[i]) 
				{
					case TOP_LEFT:
						drawImage(imageData, 0, 0);
						break;
						
					case TOP_RIGHT:
						drawImage(imageData, size.x - imageData.width, 0);
						break;
					
					case BOTTOM_LEFT:
						drawImage(imageData, 0, size.y - imageData.height);
						break;
						
					case BOTTOM_RIGHT:
						drawImage(imageData, size.x - imageData.width, size.y - imageData.height);
						break;
				}
			}
		}
	}
}
